<?php

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

abstract class abstract_model {
    
    protected $model_filhos = NULL;
    protected $validate = true;
    protected $prefix = NULL;


        /**
     * Preenche o model com os valres vindos do <bold>Form</bold>
     * 
     * @param Array $valores
     * @return abstract_model
     */
    public function populateFromForm($valores){
        foreach ($valores as $propriedade => $valor) {
            $function_name = "set$propriedade";
            if (method_exists($this ,$function_name)){
                $this->$function_name($valor);
            }else{
                if($this->model_filhos){
                    $count = 0;
                    foreach ($this->model_filhos as $model_filho) {
                        $count++;
                        if(method_exists($model_filho, $function_name)){
                            $model_filho->$function_name($valor);
                            break;
                        }else{
                            if ($count == sizeof($this->model_filhos)){
                                throw new NoPropertFoundException("Erro ao setar propriedade, metodo $function_name inexistente");
                            }
                        }
                    }
                    
//                    for($i = 0; $i < sizeof($this->model_filhos); $i++ ){
//                        if(method_exists($this->model_filhos[$i] ,$function_name)){
//                            $this->model_filhos[$i]->$function_name($value);
//                            break;
//                        }else{
//                            if ($i == (sizeof($this->model_filhos)-1)){
//                                throw new NoPropertFoundException("Erro ao setar propriedade, metodo $function_name inexistente");
//                            }
//                        }
//                    }
                }else{
                    throw new NoPropertFoundException("Erro ao setar propriedade, metodo $function_name inexistente");
                }
                
            }
        }
        return $this;
    }
    
    /**
     * Preenche o model com os valres vindos do <bold>Form</bold>
     * 
     * @param Array $valores
     * @return abstract_model
     */
    public function populateFromBanco($valores){
        foreach ($valores as $propriedade => $valor) {
            if (property_exists($this, $propriedade)){
                $this->$propriedade = $valor;
            }else{
                if($this->model_filhos){
                    $count = 0;
                    foreach($this->model_filhos as $model_filho){
                        $count++;
                        if(property_exists($model_filho ,$propriedade)){
                            $model_filho->$propriedade = $valor;
                            break;
                        }else{
                            if ($count == sizeof($this->model_filhos)){
                                throw new Exception("Erro ao setar propriedade, propriedade $propriedade inexistente");
                            }
                        }
                    }
                    
                    
//                    for($i = 0; $i < sizeof($this->model_filhos); $i++ ){
//                        if(property_exists($this->model_filhos[$i] ,$name)){
//                            $this->model_filhos[$i]->$name = $value;
//                            break;
//                        }else{
//                            if ($i == (sizeof($this->model_filhos)-1)){
//                                throw new Exception("Erro ao setar propriedade, propriedade $name inexistente");
//                            }
//                        }
//                    }
                }else{
                    throw new Exception("Erro ao setar propriedade, propriedade $propriedade inexistente");
                }
                
            }
        }
        return $this;
    }
    
    public function __get($propriedade) {
        if($this->model_filhos){
            $count = 0;
            foreach($this->model_filhos as $model_filho ){
                $count++;
                if(property_exists($model_filho ,$propriedade)){
                    return $model_filho->$propriedade;
                }else{
                    if ($count == sizeof($this->model_filhos)){
                        throw new Exception("Erro ao setar propriedade, propriedade $propriedade inexistente");
                    }
                }
            }
            
            
            
//            for($i = 0; $i < sizeof($this->model_filhos); $i++ ){
//                if(property_exists($this->model_filhos[$i] ,$propriedade)){
//                    return $this->model_filhos[$i]->$name;
//                }else{
//                    if ($i == (sizeof($this->model_filhos)-1)){
//                        throw new Exception("Erro ao setar propriedade, propriedade $propriedade inexistente");
//                    }
//                }
//            }
        }else{
            throw new Exception("Erro ao setar propriedade, propriedade $propriedade inexistente");
        }
    }
    
    public function __set($propriedade, $valor) {
        if($this->model_filhos){
            $count = 0;
            foreach($this->model_filhos as $model_filho){
                $count++;
                if(property_exists($model_filho ,$propriedade)){
                    $model_filho->$propriedade = $valor;
                    break;
                }else{
                    if ($count == sizeof($this->model_filhos)){
                        throw new Exception("Erro ao setar propriedade, propriedade $propriedade inexistente");
                    }
                }
            }
            
//            for($i = 0; $i < sizeof($this->model_filhos); $i++ ){
//                if(property_exists($this->model_filhos[$i] ,$name)){
//                    $this->model_filhos[$i]->$name = $value;
//                    break;
//                }else{
//                    if ($i == (sizeof($this->model_filhos)-1)){
//                        throw new Exception("Erro ao setar propriedade, propriedade $name inexistente");
//                    }
//                }
//            }
        }else{
            throw new Exception("Erro ao setar propriedade, propriedade $propriedade inexistente");
        }
    }
    
    public function __call($function_name, $arguments) {
        $set = "/^set./";
        $get = "/^get./";
        if (preg_match($set, $function_name)){
            if($this->model_filhos){
                $count = 0;
                foreach($this->model_filhos as $model_filho ){
                    $count++;
                    if(method_exists($model_filho ,$function_name)){
                        $model_filho->$function_name($arguments[0]);
                        break;
                    }else{
                        if ($count == sizeof($this->model_filhos)){
                            throw new NoPropertFoundException("Erro ao setar propriedade, metodo $function_name inexistente");
                        }
                    }
                }
                
                
                
//                for($i = 0; $i < sizeof($this->model_filhos); $i++ ){
//                    if(method_exists($this->model_filhos[$i] ,$function_name)){
//                        $this->model_filhos[$i]->$function_name($arguments[0]);
//                        break;
//                    }else{
//                        if ($i == (sizeof($this->model_filhos)-1)){
//                            throw new NoPropertFoundException("Erro ao setar propriedade, metodo $function_name inexistente");
//                        }
//                    }
//                }
            }else{
                throw new NoPropertFoundException("Erro ao setar propriedade, metodo $function_name inexistente");
            }
        }else if (preg_match($get, $function_name)){
            if($this->model_filhos){
                $count = 0;
                foreach($this->model_filhos as $model_filho){
                    $count++;
                    if(method_exists($model_filho ,$function_name)){
                        return $model_filho->$function_name();
                    }else{
                        if ($count == sizeof($this->model_filhos)){
                            throw new NoPropertFoundException("Erro ao setar propriedade, metodo $function_name inexistente");
                        }
                    }
                }
                
//                for($i = 0; $i < sizeof($this->model_filhos); $i++ ){
//                    if(method_exists($this->model_filhos[$i] ,$function_name)){
//                        return $this->model_filhos[$i]->$function_name();
//                    }else{
//                        if ($i == (sizeof($this->model_filhos)-1)){
//                            throw new NoPropertFoundException("Erro ao setar propriedade, metodo $function_name inexistente");
//                        }
//                    }
//                }                                                            
            }else{
                throw new NoPropertFoundException("Erro ao setar propriedade, metodo $function_name inexistente");
            }
        }else{
            throw new NoPropertFoundException("Erro ao manipular propriedade");
        }
    }
    
    protected function convert_characters($string){
        return htmlentities($string, NULL, "UTF-8");
//        return htmlentities($string, NULL, "iso-8859-1");
    }
    
    public function getModelFilho($indice){
        return $this->model_filhos[$indice];
    }
    
    public function setModelFilho($indice, $valor){
        $this->model_filhos[$indice] = $valor;
    }
    
    protected function throwValidationException($message){
        if ($this->validate){
            throw new ValidationException($message);
        }
    }
    
    public function setValidate($validate){
        $this->validate = $validate;
    }
    
    public function hasProperty($propertyName){
        $functionName = "set".$propertyName;
        return method_exists($this, $functionName);
    }
    
    public function hasPrefix($prefix){
        if($this->prefix == $prefix){
            return TRUE;
        }else if($this->model_filhos){
            foreach ($this->model_filhos as $value) {
                if ($value->hasPrefix($prefix)){
                    return TRUE;
                }
            }
        }
        return FALSE;
    }
    
}

class ValidationException extends Exception{}

class NoPropertFoundException extends Exception{}
    

?>
